//---------------------------------------------------------------------------------------------------------------------------------------------------
// <copyright file="GameLogicController.cs" company="DarkWynter Studios">
//     Copyright (C)2007 DarkWynter Studios.  All rights reserved.
// </copyright>
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------

namespace DarkWynter.Engine.Controllers
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Storage;

    using System.Diagnostics;
    #endregion

    //using DarkWynter.Engine.Globals;
    //using DarkWynter.Engine.ObjectLib;
    //using DarkWynter.Engine.Menus;

    /// <summary>
    /// Handles respawn and game over conditions based on Statics_Engine.GameSettings.gameType.
    /// </summary>
    public class GameLogicController
    {
        // CLEAN : Create a List<GameRule> in GameRules.cs
        // Use string identifier to access
        // Use Update() to execute all GameRules in List

        // Abstract GameRule contains a single method, CheckRule() 
        // Turn current code into Game componenets.
        // Create .cs file for each GameMode, with classes for each rule
        // Create and add GameScreens from GameFlow

        // See if MenuSystem can be removed from method parameters.
        // MenuSystem prob shouldn't be in GameRules


        private Stopwatch survivalRespawnTimer = null;
        private int SURVIVAL_RESPAWN_TIME = 5000;
        private int currentLevelIndex = 0;

        private int winningPlayer = -1;
        private int winningBot = -1;
        private int mostKills = 0;
        private int playersAlive = 0;


        /// <summary>
        /// Start the game timer used in game rules.
        /// </summary>
        public void StartGameTimer()
        {
            survivalRespawnTimer = new Stopwatch();
            survivalRespawnTimer.Start();
        }

        /// <summary>
        /// Check for GameOver and Respawn conditions based on Statics_Engine.GameSettings.gameType
        /// </summary>
        /// <param name="objectLibrary">Object Library currently being used.</param>
        public void Update(ObjectLibrary objectLibrary)
        {
            CheckForGameOver(ref objectLibrary);
            CheckForRespawn(ref objectLibrary);
        }

        private void CheckForRespawn(ref ObjectLibrary objectLibrary)
        {
            #region Survival
            if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.SURVIVAL)
            {
                // Only respawn after a certain time limit
                if (survivalRespawnTimer.ElapsedMilliseconds > SURVIVAL_RESPAWN_TIME)
                {
                    for (int i = 0; i < objectLibrary.bots.Count; i++)
                    {
                        if (objectLibrary.bots[i].IsAlive() == false && objectLibrary.bots[i].killedBy != -1)
                        {
                            objectLibrary.bots[i]._spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight(objectLibrary.bots[i].spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor,
                                                                                         objectLibrary.bots[i].spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor);
                            objectLibrary.bots[i].SpawnPlayer();
                        }
                    }
                    survivalRespawnTimer.Reset();
                    survivalRespawnTimer.Start();
                }
            }
            #endregion

            #region DeathMatch
            else if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.DEATHMATCH)
            {
                for (int i = 0; i < objectLibrary.humans.Count; i++)
                {
                    if (objectLibrary.humans[i].IsAlive() == false && objectLibrary.humans[i].killedBy != -1)
                    {
                        if (objectLibrary.humans[i].respawnTimer.ElapsedMilliseconds >= Statics_Engine.GameSettings.RESPAWN_DELAY)
                        {
                            objectLibrary.humans[i]._spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight(objectLibrary.humans[i].spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor,
                                                                                               objectLibrary.humans[i].spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor);
                                objectLibrary.humans[i].SpawnPlayer();
  
                        }
                    }
                }

                for (int i = 0; i < objectLibrary.bots.Count; i++)
                {
                    if (objectLibrary.bots[i].IsAlive() == false && objectLibrary.bots[i].killedBy != -1)
                    {
                        if (objectLibrary.bots[i].respawnTimer.ElapsedMilliseconds >= Statics_Engine.GameSettings.RESPAWN_DELAY)
                        {
                            objectLibrary.humans[i]._spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight(objectLibrary.humans[i].spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor,
                                                               objectLibrary.humans[i].spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor);
                                objectLibrary.bots[i].SpawnPlayer();

                        }
                    }
                }
            }
            #endregion

            #region Story Mode
            else if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.STORY_MODE)
            {
                for (int i = 0; i < objectLibrary.humans.Count; i++)
                {
                    if (objectLibrary.humans[i].IsAlive() == false && objectLibrary.humans[i].killedBy != -1)
                    {
                        if (objectLibrary.humans[i].respawnTimer.ElapsedMilliseconds >= Statics_Engine.GameSettings.RESPAWN_DELAY)
                        {
                            objectLibrary.humans[i]._spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight(objectLibrary.humans[i].spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor,
                                                                                           objectLibrary.humans[i].spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor);
                            objectLibrary.humans[i].SpawnPlayer();
                        }
                    }
                }
            }
            #endregion
        }

        // Update
        private void CheckForGameOver(ref ObjectLibrary objectLibrary)
        {
            playersAlive = objectLibrary.humans.Count;

            if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.STORY_MODE)
            {
                StoryModeRules(ref objectLibrary);
            }
            else if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.LAST_MAN_STANDING)
            {
                LastManStandingRules(ref objectLibrary);
            }
            else if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.DEATHMATCH)
            {
                DeathMatchRules(ref objectLibrary);
            }
            else if (Statics_Engine.GameSettings.gameType == Enums_Engine.GameType.SURVIVAL)
            {
                SurvivalRules(ref objectLibrary);
            }
        }

        // Rules for each game
        private void StoryModeRules(ref ObjectLibrary objectLibrary)
        {
            #region Story/LiveAction Code
            // int numKeysToAdvance = 10;
            //if (Statics_Engine.storyElement == Enums_Engine.StoryElement.CUTSCENE)
            //{
                //// Cutscene finished, Load Next Level
                //if (Statics_Engine.menuSystem.scene2.IsDone() && currentLevelIndex == 1)
                //{
                //    // Start New Level
                //    objectLibrary.LoadLevel_Stage1(XML.levelInfo[currentLevelIndex].filepath);
                //    // Load Level Data
                //    XML.LoadPlayerIndex(menuSystem);
                //    Statics_Engine.menuSystem.LevelSetupCommit(gameFlow.objectLibrary);

                //    gameFlow.Load();
                //    gameFlow.objectLibrary.humans[0].LoadPlayer(XML.playerInfo[0]);
                //    currentLevelIndex++;
                //    storyElement = StoryElement.LIVEACTION;
                //    Statics_Engine.CheckForControllers(1, gameFlow);
                //}
                //else if (menuSystem.scene1.IsDone() && currentLevelIndex == 0)
                //{
                //    // Start New Level
                //    objectLibrary.LoadLevel_Stage1(XML.levelInfo[currentLevelIndex].filepath);
                //    // Load Level Data
                //    XML.LoadPlayerIndex(menuSystem);
                //    menuSystem.LevelSetupCommit(gameFlow.objectLibrary);

                //    gameFlow.Load();
                //    gameFlow.objectLibrary.humans[0].LoadPlayer(XML.playerInfo[0]);
                //    currentLevelIndex++;
                //    storyElement = StoryElement.LIVEACTION;
                //    Statics_Engine.CheckForControllers(1, gameFlow);
                //}
            //}
            //#endregion

            //#region Live Action
            //if (Statics_Engine.storyElement == Enums_Engine.StoryElement.LIVEACTION)
            //{
            //    // Level Complete, run next cutscene
            //    //temporary.. needs to be number of keys collected
            //    if (objectLibrary.humans[0].numberOfKeysFound >= XML.GameSettings.STORYMODE_NUM_KEYS_TO_COLLECT)
            //    {
            //        // Load next CutScene
            //        storyElement = StoryElement.CUTSCENE;

            //        // Clear keys
            //        objectLibrary.humans[0].numberOfKeysFound = 0;
            //        cutSceneIndex++;

            //        // Play appropriate cutscene
            //        if (cutSceneIndex == 0)
            //        {
            //            Audio.PlayLevelSong("Scene1");
            //            menuSystem.scene1.StartCutScene();
            //        }
            //        else if (cutSceneIndex == 1)
            //        {
            //            Audio.PlayLevelSong("Scene2");
            //            menuSystem.scene2.StartCutScene();
            //        }
            //    }
            //}
            #endregion
        }
        private void LastManStandingRules(ref ObjectLibrary objectLibrary)
        {
            #region Last Man Standing Rules
            /*
            for (int i = 0; i < objectLibrary.humans.Count; i++)
            {
                if (objectLibrary.humans[i].IsAlive() == false)
                {
                    playersAlive--;
                }
                else
                {
                    winningPlayer = i + 1;
                }
            }

            if (playersAlive < 2)
            {
                int botsAlive = Statics_Engine.GameSettings.botCount;
                for (int i = 0; i < Statics_Engine.GameSettings.botCount; i++)
                {
                    if (objectLibrary.bots[i].IsAlive() == false)
                    {
                        botsAlive--;
                    }
                    else
                    {
                        winningBot = i + 1;
                    }
                }

                if (playersAlive == 1)
                {
                    if (Statics_Engine.SystemSettings.TOTAL_PLAYERS == 1 && Statics_Engine.GameSettings.botCount == 0)
                    {
                        return;
                    }
                    else if (botsAlive == 0)
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Player " + winningPlayer + " Wins!");
                        for (int i = 0; i < Statics_Engine.SystemSettings.TOTAL_PLAYERS; i++)
                        {
                            menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).SetTitle(
                                "Player " + (i + 1) + " Kills = " + objectLibrary.humans[i].kills
                                );
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                else if (playersAlive == 0)
                {
                    if (botsAlive == 1)
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Bot#" + winningBot + " Wins!");
                    }
                    else if (botsAlive == 0 && objectLibrary.bots.Count > 0)
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Everybody dies!");
                    }
                    else if (Statics_Engine.SystemSettings.TOTAL_PLAYERS == 1)
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Congratulations! You Killed Yourself!");
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        if (i < Statics_Engine.SystemSettings.TOTAL_PLAYERS)
                        {
                            menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).SetTitle(
                                "Player " + (i + 1) + " Kills = " + objectLibrary.humans[i].kills
                                );
                            menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).Show();
                        }
                        else
                        {
                            menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).Hide();
                        }
                    }

                }

                Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_OVER;
            }
            */
            #endregion
        }
        private void DeathMatchRules(ref ObjectLibrary objectLibrary)
        {
            #region Death Match Rules
            for (int i = 0; i < objectLibrary.humans.Count; i++)
            {
                if (objectLibrary.humans[i].kills >= Statics_Engine.GameSettings.maxNumberOfKills)
                {
                    winningPlayer = i + 1;
                }
            }

            for (int i = 0; i < objectLibrary.bots.Count; i++)
            {
                if (objectLibrary.bots[i].kills >= Statics_Engine.GameSettings.maxNumberOfKills)
                {
                    winningBot = i + 1;
                }
            }

            if (winningPlayer > 0)
            {
                //menuSystem.GetGameOverMenuElement(0).SetTitle("Player " + winningPlayer + " Wins!");
                //for (int i = 0; i < 4; i++)
                //{
                //    if (i < Statics_Engine.SystemSettings.TOTAL_PLAYERS)
                //    {
                //        menuSystem.GetGameOverMenuElement(i + 2).SetTitle(
                //            "Player " + (i + 1) + " Kills = " + objectLibrary.humans[i].kills);
                //        menuSystem.GetGameOverMenuElement(i + 2).Show();
                //    }
                //    else
                //    {
                //        menuSystem.GetGameOverMenuElement(i + 2).Hide();
                //    }
                //}

                Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_OVER;
            }
            else if (winningBot > 0)
            {
                //menuSystem.GetGameOverMenuElement(0).SetTitle("Bot " + winningBot + " Wins!");
                //for (int i = 0; i < 4; i++)
                //{
                //    if (i < Statics_Engine.SystemSettings.TOTAL_PLAYERS)
                //    {
                //        menuSystem.GetGameOverMenuElement(i + 2).SetTitle(
                //            "Player " + (i + 1) + " Kills = " + objectLibrary.humans[i].kills);
                //        menuSystem.GetGameOverMenuElement(i + 2).Show();
                //    }
                //    else
                //    {
                //        menuSystem.GetGameOverMenuElement(i + 2).Hide();
                //    }
                //}

                Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_OVER;
            }
            #endregion
        }
        private void SurvivalRules(ref ObjectLibrary objectLibrary)
        {
            #region Survival Mode Rules
            /*
            for (int i = 0; i < objectLibrary.humans.Count; i++)
            {
                if (objectLibrary.humans[i].IsAlive() == true)
                {
                    return;
                }
                if (objectLibrary.humans[i].kills >= mostKills)
                {
                    winningPlayer = i + 1;
                    mostKills = objectLibrary.humans[i].kills;
                }
            }

            if (mostKills == 0)
            {
                //no one killed anyone
                menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Zero kills? Are you kidding me?!");
                for (int i = 0; i < 4; i++)
                {
                    menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).Hide();
                }
            }
            else
            {
                menuSystem.gameOverScreen.GetMenu().GetMenuElement(0).SetTitle("Player " + winningPlayer + " Wins!");
                for (int i = 0; i < 4; i++)
                {
                    if (i < Statics_Engine.SystemSettings.TOTAL_PLAYERS)
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).SetTitle(
                            "Player " + (i + 1) + " Kills = " + objectLibrary.humans[i].kills
                            );
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).Show();
                    }
                    else
                    {
                        menuSystem.gameOverScreen.GetMenu().GetMenuElement(i + 2).Hide();
                    }
                }
            }
            Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_OVER;
            */
            #endregion
        }
    }
}